﻿using System;
using System.Diagnostics.Contracts;
using Midi;
using Microsoft.Pex.Framework;

namespace AutomaTones.HW_Sense_Compute {
    /// <summary>
    /// Looks through the installed midi devices and connects the Launchpad if present.
    /// </summary>
    /// <author>Anders Bech Mellson, anbh@itu.dk</author>
    [PexClass]
    class ConnectLaunchpad:IConnect {
        public static InputDevice In;
        public static OutputDevice Out;

        int? _inDevice, _outDevice;
        const String Error = "No Launchpad present. Have you installed the driver?";
        
        public ConnectLaunchpad() {
//            Contract.Requires(!this.Connected());
            In = InputDevice.InstalledDevices[GetInDeviceNumber()];
            Out = OutputDevice.InstalledDevices[GetOutDeviceNumber()];
        }

        /// <summary>
        /// Checks whether a Launchpad is connected or not.
        /// </summary>
        [PexMethod]
        public bool Connected() {
            return In!=null && Out!=null;
        }

        /// <summary>
        /// Scans through the connected input devices and sets _inDevice to match the one containing the Launchpad.
        /// </summary>
        private void SetInDeviceNumber() {
            if (InputDevice.InstalledDevices.Count == 0) {
                throw new System.ArgumentException(Error);
            }
            int i = 0;
            foreach (InputDevice device in InputDevice.InstalledDevices) {
                if (device.Name.Contains("Launchpad")) {
                    _inDevice = i;
                    break;
                }
                i++;
            }
        }

        /// <summary>
        /// Tries to get the inDevice int. Throws an exception that is handled by MainController if no Launchpad is connected.
        /// </summary>
        private int GetInDeviceNumber() {
            SetInDeviceNumber();
            if (_inDevice == null)
                throw new ArgumentException(Error);
            return (int)_inDevice;
        }

        /// <summary>
        /// Scans through the connected output devices and sets _outDevice to match the one containing the Launchpad.
        /// </summary>
        private void SetOutDeviceNumber() {
            if (OutputDevice.InstalledDevices.Count == 0) {
                throw new System.ArgumentException(Error);
            }
            int i = 0;
            foreach (OutputDevice device in OutputDevice.InstalledDevices) {
                if (device.Name.Contains("Launchpad")) {
                    _outDevice = i;
                    break;
                }
                i++;
            }
        }

        /// <summary>
        /// Tries to get the outDevice int. Throws an exception that is handled by MainController if no Launchpad is connected.
        /// </summary>
        private int GetOutDeviceNumber() {
            SetOutDeviceNumber();
            if (_outDevice == null)
                throw new System.ArgumentException(Error);
            return (int)_outDevice;
        }
    }
}